/*
 * Dcm_UDS0x19.c
 *
 *  Created on: 2018-1-16
 *      Author: Shute
 */
#include "UDS.h"



/****************************************************************
	     UDS:ReadDTCInformation (19 hex) service
 ***************************************************************/
#if(STD_ON == DCM_UDS_SERVICE0X19_ENABLED)



static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_01(uint8 ProtocolCtrlId);

static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_02(uint8 ProtocolCtrlId);


static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_04(uint8 ProtocolCtrlId);

static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_0A(uint8 ProtocolCtrlId);


static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x19SubfunctionAnalyse(
        uint8 ProtocolCtrlId,
        uint8 Subfunction);
        
#if(STD_ON == DCM_UDS_SERVICE0X19_01_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_01(uint8 ProtocolCtrlId)
{
	uint8    TxChannelCtrlIndex;
	uint8    TxChannelCfgIndex;
	uint8    DtcStatusMask;
	uint8    MsgCtrlId;
	uint16   DtcCount = 0;
	uint16   Offset;
	boolean  NotAllowedFlag = FALSE;
	boolean  PendingFlag = FALSE;
	Std_ReturnType  ret;
	Dcm_MsgLenType  MsgLen;
	Dem_ReturnSetFilterType    ReturnSetDTCFilter;
	Dem_ReturnGetNumberOfFilteredDTCType  ReturnGetNumberOfFilteredDTC;

	MsgCtrlId = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
    /**************************************************/
	/*check the massage length*/
	if (DCM_UDS0X19_SUBFUNC0X01_REQ_DATA_LENGTH != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
	{
		/*the length of massage is not correct,send NRC 0x13*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

	/*find Tx buffer and offset*/
	TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
	TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
	Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

    /**************************************************/
	/*Sub-function:0x01*/
	MsgLen = 2u;
	DtcStatusMask  = Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[2];

	/*obtain DTCStatusAvailabilityMask*/
	ret = Dem_DcmGetDTCStatusAvailabilityMask(&Dcm_Channel[Offset + MsgLen]);
	if (E_OK == ret)
	{
		/*one byte for the storage of DTC status availability mask*/
		MsgLen = MsgLen + 1u;

		/*get and store DTCFormatIdentifier*/
		Dcm_Channel[(uint32)Offset + MsgLen] = Dem_DcmGetTranslationType();
		MsgLen = MsgLen + 1u;

		if (DtcStatusMask == 0u)
		{
            Dcm_Channel[(uint32)Offset + MsgLen] = (uint8)0;
            MsgLen = MsgLen + 1u;
            Dcm_Channel[(uint32)Offset + MsgLen] = (uint8)0;
            MsgLen = MsgLen + 1u;
		}
		else
		{
	        /*set DTC filter*/
	        ReturnSetDTCFilter = Dem_DcmSetDTCFilter(   DtcStatusMask,
	                                                DEM_DTC_KIND_ALL_DTCS,
	                                                DEM_DTC_FORMAT_UDS,
	                                                DEM_DTC_ORIGIN_PRIMARY_MEMORY,
	                                                FALSE,
	                                                DEM_SEVERITY_NO_SEVERITY,
	                                                FALSE   );
	        if (DEM_FILTER_ACCEPTED == ReturnSetDTCFilter)
	        {
	            /*get the number of required DTC*/
	            ReturnGetNumberOfFilteredDTC = Dem_DcmGetNumberOfFilteredDTC(&DtcCount);
	            switch(ReturnGetNumberOfFilteredDTC)
	            {
	                case DEM_NUMBER_OK:
	                    Dcm_Channel[(uint32)Offset + MsgLen] = (uint8)(DtcCount>>8u);
	                    MsgLen = MsgLen + 1u;
	                    Dcm_Channel[(uint32)Offset + MsgLen] = (uint8)DtcCount;
	                    MsgLen = MsgLen + 1u;
	                    break;
	                case DEM_NUMBER_FAILED:
	                    NotAllowedFlag = TRUE;
	                    break;
	                case DEM_NUMBER_PENDING:
	                    PendingFlag = TRUE;
	                    break;
	                default:
	                    NotAllowedFlag = TRUE;
	                    break;
	            }
	        }
	        else
	        {
	            /*if fail to set DTC filter*/
	            NotAllowedFlag  = TRUE;
	        }
		}
	}
	else
	{
		NotAllowedFlag = TRUE;
	}
    /**************************************************/
	if (TRUE == NotAllowedFlag)
	{
		/*if fail to get any request information,send NRC 0x22*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	else if (TRUE == PendingFlag)
	{
		/*if some request info is not available yet,enter pending and wait for the next cycle*/
		Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
		return DCM_E_PENDING;
	}
	else
	{
        /* check tx data length */
        if((MsgLen) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
        {
            /*Pdu length is bigger than buffer size,ignore the request message */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
		/*assemble positive response*/
		Dcm_Channel[Offset] = 0x59;
		Dcm_Channel[Offset + 1u] = 0x01;
		SchM_Enter_Dcm(Dcm_MsgCtrl);
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = MsgLen;
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = MsgLen;
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
		SchM_Exit_Dcm(Dcm_MsgCtrl);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_OK;
	}

}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/************************************/
#if(STD_ON == DCM_UDS_SERVICE0X19_02_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_02(uint8 ProtocolCtrlId)
{
	uint8     TxChannelCtrlIndex;
	uint8     TxChannelCfgIndex;
	uint8     DtcStatus;
	uint8     DtcStatusMask;
	uint8     MsgCtrlId;
	uint16    Offset;
	uint16    Index;
	uint16    DtcCount = 0;
	uint32    Dtc;
	boolean   NotAllowedFlag = FALSE;
	boolean   PendingFlag = FALSE;
	boolean   Flag;
	Std_ReturnType  ret;
	Dcm_MsgLenType  MsgLen;
	Dem_ReturnSetFilterType         ReturnSetDTCFilter;
	Dem_ReturnGetNextFilteredElementType   ReturnGetNextFilteredDTC;
	Dem_ReturnGetNumberOfFilteredDTCType  ReturnGetNumberOfFilteredDTC;

	MsgCtrlId = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
    /**************************************************/
	/*check the massage length*/
	if (DCM_UDS0X19_SUBFUNC0X02_REQ_DATA_LENGTH != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
	{
		/*the length of massage is not correct,send NRC 0x13*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

    /**************************************************/
	/*find Tx buffer and offset*/
	TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
	TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
	Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

	MsgLen = 2u;	/*keep two bytes to store response SID and echo of sub-function*/
	DtcStatusMask  = Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[2];

#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
    if (0u == Dcm_PageBufferData.PageIndex)
    {
        Dcm_PageBufferData.PageTxOK = FALSE;
#endif
        Dcm_Channel[Offset] = 0x59;
        Dcm_Channel[Offset + 1u] = 0x02;
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
        Dcm_PageBufferData.LastFilled = TRUE;
    }
    else
    {
        if (Dcm_PageBufferData.PageTxOK != TRUE)
        {
            Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
            return DCM_E_PENDING;
        }
        MsgLen = 0u;
        Index = Dcm_PageBufferData.IloopOne;
        Dcm_PageBufferData.PageTxOK = FALSE;
        Dcm_PageBufferData.LastFilled = TRUE;
    }
#endif

	/*get DTCStatusAvailabilityMask*/
	ret = Dem_DcmGetDTCStatusAvailabilityMask(&Dcm_Channel[Offset + MsgLen]);
	if (E_OK == ret)
	{
		/*if DTCStatusAvailabilityMask = 0,no DTC*/
        if (0u == Dcm_Channel[Offset + MsgLen])
        {
        	MsgLen = MsgLen + 1u;
        }
		/*if DTCStatusAvailabilityMask !=0,have DTC*/
        else
		{
        	MsgLen = MsgLen + 1u;
			/*set DTC filter*/
        	if (DtcStatusMask != 0u)
        	{
                ReturnSetDTCFilter = Dem_DcmSetDTCFilter(	DtcStatusMask,
                                                        DEM_DTC_KIND_ALL_DTCS,
                                                        DEM_DTC_FORMAT_UDS,
                                                        DEM_DTC_ORIGIN_PRIMARY_MEMORY,
                                                        FALSE,
                                                        DEM_SEVERITY_NO_SEVERITY,
                                                        FALSE);
                if (DEM_FILTER_ACCEPTED == ReturnSetDTCFilter)
                {
                    ReturnGetNumberOfFilteredDTC = Dem_DcmGetNumberOfFilteredDTC(&DtcCount);
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                    if (Dcm_PageBufferData.TotalSize != 0UL)
                    {
                        DtcCount = Dcm_PageBufferData.TotalDtcCount;
                    }
#endif
                    switch(ReturnGetNumberOfFilteredDTC)
                    {
                        case DEM_NUMBER_OK:
                             Flag = FALSE;
                             for(Index = 0; (Index<DtcCount)&&(FALSE==Flag)
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                             && ((Dcm_PageBufferData.LastFilled == TRUE)
                                     || (Dcm_PageBufferData.TotalSize == 0UL))
#endif
                             ; Index++)
                             {
                                ReturnGetNextFilteredDTC = Dem_DcmGetNextFilteredDTC(&Dtc,&DtcStatus);
                                switch(ReturnGetNextFilteredDTC)
                                {
                                    case  DEM_FILTERED_OK:
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                                          if (((Dcm_PageBufferData.TotalSize == 0UL)
                                                  || (Index > Dcm_PageBufferData.IloopOne)
                                                  || (Index == 0u))
                                                  && (((Dcm_PageBufferData.TotalSize != 0UL)
                                                          && (Dcm_PageBufferData.TotalDtcCount > Index))
                                                          || (Dcm_PageBufferData.TotalSize == 0UL)))
#endif
                                          {
                                              Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc >> 16u);
                                              MsgLen  = MsgLen + 1u;
                                              Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc >> 8u);
                                              MsgLen  = MsgLen + 1u;
                                              Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc);
                                              MsgLen  = MsgLen + 1u;
                                              Dcm_Channel[Offset + MsgLen] = DtcStatus;
                                              MsgLen  = MsgLen + 1u;
                                          }
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                                          if ((MsgLen) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].
                                                  Dcm_DslBufferSize))
                                          {
                                              Dcm_PageBufferData.LastFilled = FALSE;
                                          }
#endif
                                          break;
                                    case  DEM_FILTERED_NO_MATCHING_ELEMENT:
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                                          if ((Dcm_PageBufferData.TotalSize != 0UL)
                                                  && (Dcm_PageBufferData.TotalDtcCount > Index))
                                          {
                                              Dcm_Channel[Offset + MsgLen] = 0u;
                                              MsgLen  = MsgLen + 1u;
                                              Dcm_Channel[Offset + MsgLen] = 0u;
                                              MsgLen  = MsgLen + 1u;
                                              Dcm_Channel[Offset + MsgLen] = 0u;
                                              MsgLen  = MsgLen + 1u;
                                              Dcm_Channel[Offset + MsgLen] = 0u;
                                              MsgLen  = MsgLen + 1u;
                                              if ((MsgLen)
                                                 > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].
                                                         Dcm_DslBufferSize))
                                              {
                                                  Dcm_PageBufferData.LastFilled = FALSE;
                                              }
                                          }
                                          else
#endif
                                          {
                                              NotAllowedFlag = TRUE;
                                              Flag = TRUE;
                                          }
                                          break;
                                    case  DEM_FILTERED_PENDING:
                                          PendingFlag = TRUE;
                                          Flag = TRUE;
                                          break;
                                    case  DEM_FILTERED_BUFFER_TOO_SMALL:
                                          NotAllowedFlag = TRUE;
                                          Flag = TRUE;
                                          break;
                                    default:
                                          NotAllowedFlag = TRUE;
                                          Flag = TRUE;
                                          break;
                                }
                            }
                            break;
                        case DEM_NUMBER_FAILED:
                            NotAllowedFlag = TRUE;
                            break;
                        case DEM_NUMBER_PENDING:
                            PendingFlag = TRUE;
                            break;
                        default:
                            NotAllowedFlag = TRUE;
                            break;
                    }
                }
                else
                {
                    /*fail to set DTC Filter*/
                    NotAllowedFlag  = TRUE;
                }
        	}
		}
	}
	else
	{
		NotAllowedFlag = TRUE;
	}
	/************************************************/
	if (TRUE == NotAllowedFlag)
	{
		/*if fail to get any request information,send NRC 0x22*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	else if (TRUE == PendingFlag)
	{
		/*if some request info is not available yet,enter pending and wait for the next cycle*/
		Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
		return DCM_E_PENDING;
	}
	else
	{
        /* check tx data length */
        if
#if(STD_ON == DCM_PAGEDBUFFER_ENABLED)
          (
#endif
           ((MsgLen) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
#if(STD_ON == DCM_PAGEDBUFFER_ENABLED)
            || (0UL != Dcm_PageBufferData.TotalSize))
        {
            if(0UL == Dcm_PageBufferData.TotalSize)
            {
                Dcm_PageBufferData.TotalSize = MsgLen;
                Dcm_PageBufferData.TotalDtcCount = DtcCount;
                DsdInternal_StartPagedProcessing(ProtocolCtrlId);
            }
            else
            {
                if (Dcm_PageBufferData.LastFilled == TRUE)
                {
                    Dcm_PageBufferData.IloopOne = Index;
                    Dcm_PageBufferData.ThisPageSize = (uint16)MsgLen;
                }
                else
                {
                    Dcm_PageBufferData.IloopOne = Index - 1u;
                    Dcm_PageBufferData.ThisPageSize = (uint16)(MsgLen - 4u);
                }
                Dcm_PageBufferData.PageIndex += 1u;
                Dcm_PageBufferData.Filled = TRUE;

                DsdInternal_ProcessPage(ProtocolCtrlId);
                if (Dcm_PageBufferData.TimeOut == TRUE)
                {
                    return E_NOT_OK;
                }
                Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
                return DCM_E_PENDING;
            }
            if (Dcm_PageBufferData.TotalSize > Dcm_DslCfg.pDcmDslProtocol->
                    pDcmDslProtocolRow[ProtocolCtrlId].DcmDslProtocolMaximumResponseSize)
            {
                /*Pdu length is bigger than Page buffer max size */
                (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
                DsdInternal_ProcessingDone(ProtocolCtrlId);
                DslInternal_InitPageBuffer();
                return E_NOT_OK;
            }
            Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
            return DCM_E_PENDING;
        }
#else
        {
            /*Pdu length is bigger than buffer size,ignore the request message */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
#endif
		/*assemble positive response*/
		SchM_Enter_Dcm(Dcm_MsgCtrl);
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = MsgLen;
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = MsgLen;
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
		SchM_Exit_Dcm(Dcm_MsgCtrl);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_OK;
	}

}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/****************************************/
#if(STD_ON == DCM_UDS_SERVICE0X19_03_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_03(uint8 ProtocolCtrlId)
{
    uint8     TxChannelCtrlIndex;
    uint8     TxChannelCfgIndex;
    uint8     SnapshotRecord;
    uint8     MsgCtrlId;
    uint16    Offset;
    uint32    Dtc;
    Dcm_MsgLenType  MsgLen;
    Dem_ReturnGetNextFilteredElementType   ReturnGetNextFilteredElement;
    uint16 NumberOfFilteredRecords = 0;
    uint16 iloop = 0;

    MsgCtrlId = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
    /**************************************************/
    /*check the massage length*/
    if (DCM_UDS0X19_SUBFUNC0X03_REQ_DATA_LENGTH
            != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
    {
        /*the length of massage is not correct,send NRC 0x13*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
    if (0 == Dcm_PageBufferData.PageIndex)
    {
        Dcm_PageBufferData.PageTxOK = FALSE;
        Dcm_PageBufferData.LastFilled = TRUE;
    }
    else
    {
        if (Dcm_PageBufferData.PageTxOK != TRUE)
        {
            Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
            return DCM_E_PENDING;
        }
        Dcm_PageBufferData.PageTxOK = FALSE;
        Dcm_PageBufferData.LastFilled = TRUE;
    }
#endif

    /**************************************************/
    /*find Tx buffer and offset*/
    TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
    TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
    Offset      = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

    if (DEM_WRONG_FILTER == Dem_DcmSetFreezeFrameRecordFilter(DEM_DTC_FORMAT_UDS,&NumberOfFilteredRecords))
    {
        /*if fail to set filter,send NRC 0x31*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

    MsgLen = 2u;

    for (iloop = 0;
          ((iloop < NumberOfFilteredRecords)
               && (ReturnGetNextFilteredElement != DEM_FILTERED_NO_MATCHING_ELEMENT));
          iloop++)
    {
        /*read-out the corresponding FreezeFrameRecord*/
        ReturnGetNextFilteredElement = Dem_DcmGetNextFilteredRecord(&Dtc,&SnapshotRecord);
        if (ReturnGetNextFilteredElement == DEM_FILTERED_OK)
        {
#if(STD_ON == DCM_PAGEDBUFFER_ENABLED)
            if (iloop < Dcm_PageBufferData.IloopOne)
            {
                /*do nothing*/
            }
            else
            {
#endif
                Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc>>16u);
                MsgLen = MsgLen + 1u;
                Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc>>8u);
                MsgLen = MsgLen + 1u;
                Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc);
                MsgLen = MsgLen + 1u;
                Dcm_Channel[Offset + MsgLen] = SnapshotRecord;
                MsgLen = MsgLen + 1u;
#if(STD_ON == DCM_PAGEDBUFFER_ENABLED)
                if ((MsgLen)
                   > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].
                           Dcm_DslBufferSize))
                {
                    Dcm_PageBufferData.LastFilled = FALSE;
                }
            }
#endif
        }
    }

    /* check tx data length */
      if
  #if(STD_ON == DCM_PAGEDBUFFER_ENABLED)
        (
  #endif
         ((MsgLen) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
  #if(STD_ON == DCM_PAGEDBUFFER_ENABLED)
          || (0UL != Dcm_PageBufferData.TotalSize))
      {
          if(0UL == Dcm_PageBufferData.TotalSize)
          {
              Dcm_PageBufferData.TotalSize = MsgLen;
              DsdInternal_StartPagedProcessing(ProtocolCtrlId);
          }
          else
          {
              if (Dcm_PageBufferData.LastFilled == TRUE)
              {
                  Dcm_PageBufferData.IloopOne = iloop;
                  Dcm_PageBufferData.ThisPageSize = (uint16)MsgLen;
              }
              else
              {
                  Dcm_PageBufferData.IloopOne = iloop - 1u;
                  Dcm_PageBufferData.ThisPageSize = (uint16)(MsgLen - 4u);
              }
              Dcm_PageBufferData.PageIndex += 1u;
              Dcm_PageBufferData.Filled = TRUE;

              DsdInternal_ProcessPage(ProtocolCtrlId);
              if (Dcm_PageBufferData.TimeOut == TRUE)
              {
                  return E_NOT_OK;
              }
              Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
              return DCM_E_PENDING;
          }
          if (Dcm_PageBufferData.TotalSize > Dcm_DslCfg.pDcmDslProtocol->
                  pDcmDslProtocolRow[ProtocolCtrlId].DcmDslProtocolMaximumResponseSize)
          {
              /*Pdu length is bigger than Page buffer max size */
              (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
              DsdInternal_ProcessingDone(ProtocolCtrlId);
              DslInternal_InitPageBuffer();
              return E_NOT_OK;
          }
          Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
          return DCM_E_PENDING;
      }
  #else
      {
          /*Pdu length is bigger than buffer size,ignore the request message */
          (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
          DsdInternal_ProcessingDone(ProtocolCtrlId);
          return E_NOT_OK;
      }
  #endif

    /*assemble positive response*/
    Dcm_Channel[Offset] = 0x59;
    Dcm_Channel[Offset + 1u] = 0x03;
    SchM_Enter_Dcm(Dcm_MsgCtrl);
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = MsgLen;
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = MsgLen;
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
    SchM_Exit_Dcm(Dcm_MsgCtrl);
    DsdInternal_ProcessingDone(ProtocolCtrlId);
    return  E_OK;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/****************************************/
#if(STD_ON == DCM_UDS_SERVICE0X19_04_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_04(uint8 ProtocolCtrlId)
{
	uint8     TxChannelCtrlIndex;
	uint8     TxChannelCfgIndex;
	uint16    CurBufferSize;
	uint8     DtcStatus;
	uint8     SnapshotRecord;
	uint8     Index;
	uint8     MsgCtrlId;
	uint16    ChannelSize;
	uint16    Offset;
	uint32    Dtc;
	boolean   NotAllowedFlag = FALSE;
	boolean   PendingFlag = FALSE;
	Dcm_MsgLenType  MsgLen;
	Dem_ReturnGetFreezeFrameDataByDTCType retGetFreezeFrameDataByDTC;
	Dem_ReturnDisableDTCRecordUpdateType ReturnDisableDTCRecordUpdate;

	MsgCtrlId = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
    /**************************************************/
	/*check the massage length*/
	if (DCM_UDS0X19_SUBFUNC0X04_REQ_DATA_LENGTH
	        != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
	{
		/*the length of massage is not correct,send NRC 0x13*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

    /**************************************************/
	/*find Tx buffer and offset*/
	TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
	TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
	ChannelSize = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].Dcm_DslBufferSize;
	Offset      = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

	/*get DTC and reoord number from request message*/
	Dtc = (((uint32)Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[2])<< 16u)
	 	 |(((uint32)Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[3])<< 8u)
	 	 |(((uint32)Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[4]));
	SnapshotRecord = Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[5];

	/*read-out the correspoding DtcStatus of required DTC*/
	(void)Dem_DcmGetStatusOfDTC(Dtc,DEM_DTC_ORIGIN_PRIMARY_MEMORY,&DtcStatus);
    MsgLen = 2u;
    Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc>>16u);
    MsgLen = MsgLen + 1u;
    Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc>>8u);
    MsgLen = MsgLen + 1u;
    Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc);
    MsgLen = MsgLen + 1u;
    Dcm_Channel[Offset + MsgLen] = DtcStatus;
    MsgLen = MsgLen + 1u;

    if(0xFFu == SnapshotRecord)
    {
        /*read-out all required snapshot datum*/
        ReturnDisableDTCRecordUpdate = Dem_DcmDisableDTCRecordUpdate(Dtc, DEM_DTC_ORIGIN_PRIMARY_MEMORY);
        if(DEM_DISABLE_DTCRECUP_OK == ReturnDisableDTCRecordUpdate)
        {
            for(Index = 1u; Index<0xEFu; Index++)
            {
                /*reserve 1byte to store record number*/
                CurBufferSize = (ChannelSize - (uint16)MsgLen - 1u);
                retGetFreezeFrameDataByDTC = Dem_DcmGetFreezeFrameDataByDTC(Dtc,
                                     DEM_DTC_ORIGIN_PRIMARY_MEMORY,
                                     Index,
                                     &Dcm_Channel[Offset + (uint16)MsgLen + 1u],
                                     &CurBufferSize);
                if(DEM_GET_FFDATABYDTC_OK == retGetFreezeFrameDataByDTC)
                {
                    Dcm_Channel[Offset + MsgLen] = Index;
                    MsgLen = MsgLen + CurBufferSize + 1u;
                }
                else if(DEM_GET_FFDATABYDTC_PENDING == retGetFreezeFrameDataByDTC)
                {
                    PendingFlag = TRUE;
                    break;
                }
                else if ((DEM_GET_FFDATABYDTC_WRONG_DTC == retGetFreezeFrameDataByDTC)||
                        (DEM_GET_FFDATABYDTC_WRONG_DTCORIGIN == retGetFreezeFrameDataByDTC))
                {
                    /*if fail to get any request information,send NRC 0x31*/
                    (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
                    DsdInternal_ProcessingDone(ProtocolCtrlId);
                    (void)Dem_DcmEnableDTCRecordUpdate();
                    return E_NOT_OK;
                }
                else
                {
                    /*nothing to do,Keep the format consistent*/
                }
            }
            if(E_OK != Dem_DcmEnableDTCRecordUpdate())
            {
                NotAllowedFlag = TRUE;
            }
        }
        else if (DEM_DISABLE_DTCRECUP_WRONG_DTC == ReturnDisableDTCRecordUpdate)
        {
            NotAllowedFlag = TRUE;
        }
        else
        {}
    }
    else
    {
        /*read-out the correspoding snapshot by SnapshotRecord*/
        ReturnDisableDTCRecordUpdate = Dem_DcmDisableDTCRecordUpdate(Dtc, DEM_DTC_ORIGIN_PRIMARY_MEMORY);
        if(DEM_DISABLE_DTCRECUP_OK == ReturnDisableDTCRecordUpdate)
        {
            /*reserve 1byte to store record number*/
            CurBufferSize = (ChannelSize - (uint16)MsgLen - 1u);
            retGetFreezeFrameDataByDTC = Dem_DcmGetFreezeFrameDataByDTC(Dtc,
                                 DEM_DTC_ORIGIN_PRIMARY_MEMORY,
                                 SnapshotRecord,
                                 &Dcm_Channel[Offset + (uint16)MsgLen+1u],
                                 &CurBufferSize);
            if(DEM_GET_FFDATABYDTC_OK == retGetFreezeFrameDataByDTC)
            {
                Dcm_Channel[Offset + (uint16)MsgLen] = SnapshotRecord;
                MsgLen = MsgLen + CurBufferSize + 1u;
            }
            else if(DEM_GET_FFDATABYDTC_PENDING == retGetFreezeFrameDataByDTC)
            {
                PendingFlag = TRUE;
            }
            else if ((DEM_GET_FFDATABYDTC_WRONG_DTC == retGetFreezeFrameDataByDTC)||
                    (DEM_GET_FFDATABYDTC_WRONG_DTCORIGIN == retGetFreezeFrameDataByDTC)||
                    (DEM_GET_FFDATABYDTC_WRONG_RECORDNUMBER == retGetFreezeFrameDataByDTC))
            {
                /*if fail to get any request information,send NRC 0x31*/
                (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
                DsdInternal_ProcessingDone(ProtocolCtrlId);
                (void)Dem_DcmEnableDTCRecordUpdate();
                return E_NOT_OK;
            }
            else
            {
                /*nothing to do,Keep the format consistent*/
            }

            if(E_OK != Dem_DcmEnableDTCRecordUpdate())
            {
                NotAllowedFlag = TRUE;
            }
        }
        else if (DEM_DISABLE_DTCRECUP_WRONG_DTC == ReturnDisableDTCRecordUpdate)
        {
            NotAllowedFlag = TRUE;
        }
        else
        {}
    }

	if(TRUE == NotAllowedFlag)
	{
		/*if fail to get any request information,send NRC 0x31*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	else if(TRUE == PendingFlag)
	{
		/*if some request info is not available yet,enter pending and wait for the next cycle*/
		Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
		return DCM_E_PENDING;
	}
	else
	{
        /* check tx data length */
        if((MsgLen) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
        {
            /*Pdu length is bigger than buffer size,ignore the request message */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
		/*assemble positive response*/
		Dcm_Channel[Offset] = 0x59;
		Dcm_Channel[Offset + 1u] = 0x04;
		SchM_Enter_Dcm(Dcm_MsgCtrl);
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = MsgLen;
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = MsgLen;
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
		SchM_Exit_Dcm(Dcm_MsgCtrl);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_OK;
	}
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/******************************************/
#if(STD_ON == DCM_UDS_SERVICE0X19_06_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_06(uint8 ProtocolCtrlId)
{
	uint8     TxChannelCtrlIndex;
	uint8     TxChannelCfgIndex;
	uint16    CurChannelSize;
	uint8     Index;
	uint8     DtcStatus;
	uint8     DtcExtendedDataRecordNumber;
	uint8     MsgCtrlId;
	uint16    ChannelSize;
	uint16    Offset;
	uint32    Dtc;
	boolean   NotAllowedFlag = FALSE;
	boolean   PendingFlag = FALSE;
	Dcm_MsgLenType  MsgLen;
	Dem_ReturnGetExtendedDataRecordByDTCType  ReturnGetExtendedDataRecord;
    Dem_ReturnDisableDTCRecordUpdateType ReturnDisableDTCRecordUpdate;

	MsgCtrlId = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
	/*check the massage length*/
	if (DCM_UDS0X19_SUBFUNC0X06_REQ_DATA_LENGTH != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
	{
		/*the length of massage is not correct,send NRC 0x13*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

	/*find Tx buffer and offset*/
	TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
	TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
	ChannelSize = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].Dcm_DslBufferSize;
	Offset      = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

	/*get DTC and record number from request message*/
	Dtc = (((uint32)Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[2]) << 16u)
		 |(((uint32)Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[3]) << 8u)
		 |(((uint32)Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[4]));
	DtcExtendedDataRecordNumber = Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[5];
	/*read-out the corresponding DtcStatus of required DTC*/
	(void)Dem_DcmGetStatusOfDTC(Dtc,DEM_DTC_ORIGIN_PRIMARY_MEMORY,&DtcStatus);
    MsgLen = 2u;
    Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc >> 16u);
    MsgLen = MsgLen + 1u;
    Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc >> 8u);
    MsgLen = MsgLen + 1u;
    Dcm_Channel[Offset + MsgLen] = (uint8) Dtc;
    MsgLen = MsgLen + 1u;
    Dcm_Channel[Offset + MsgLen] = DtcStatus;
    MsgLen = MsgLen + 1u;

    /*read-out the corresponding extended data of DtcExtendedDataRecordNumber*/
    /*disable DTC record update*/
    ReturnDisableDTCRecordUpdate = Dem_DcmDisableDTCRecordUpdate(Dtc, DEM_DTC_ORIGIN_PRIMARY_MEMORY);
    if(DEM_DISABLE_DTCRECUP_OK == ReturnDisableDTCRecordUpdate)
    {
        if ((0xFEu == DtcExtendedDataRecordNumber) || (0xFFu == DtcExtendedDataRecordNumber))
        {
            /*DTC + (equal to 0xFF or 0xFE)*/
            /*read-out the corresponding extended data of required DTC*/
            if (0xFEu == DtcExtendedDataRecordNumber)
            {
                /*read-out OBD relative extended data of required DTC*/
                Index = 0x90u;
            }
            else
            {
                Index = 0x01u;
            }

            for (; Index <= 0xEFu; Index++)
            {
                /*calculate the remained size of Tx buffer,keep one byte to store record number*/
                CurChannelSize = (ChannelSize - (uint16)MsgLen - 1u);
                ReturnGetExtendedDataRecord = Dem_DcmGetExtendedDataRecordByDTC(
                                                Dtc,
                                                DEM_DTC_ORIGIN_PRIMARY_MEMORY,
                                                Index,
                                                &Dcm_Channel[Offset + (uint16)MsgLen + 1u],
                                                &CurChannelSize);
                if ((DEM_RECORD_OK == ReturnGetExtendedDataRecord)&&(CurChannelSize != 0u))
                {
                    /*save DTCExtendDataRecordNumber to Tx buffer*/
                    Dcm_Channel[Offset + MsgLen] = Index;
                    MsgLen = MsgLen + 1u;
                    /*successfully store extended data,increase MsgLen*/
                    MsgLen = MsgLen + CurChannelSize;
                }
                else if (DEM_RECORD_PENDING == ReturnGetExtendedDataRecord)
                {
                    PendingFlag = TRUE;
                    break;
                }
                else if (0xFFu == DtcExtendedDataRecordNumber)
                {
                    if ((DEM_RECORD_WRONG_DTC == ReturnGetExtendedDataRecord)||
                            (DEM_RECORD_WRONG_DTCORIGIN == ReturnGetExtendedDataRecord)||
                            ((DEM_RECORD_WRONG_NUMBER == ReturnGetExtendedDataRecord)
                              && (MsgLen == 6u)
                              && (Index == 0xEFu))
                            )
                    {
                        /*if fail to get any request information,send NRC 0x31*/
                        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
                        DsdInternal_ProcessingDone(ProtocolCtrlId);
                        (void)Dem_DcmEnableDTCRecordUpdate();
                        return E_NOT_OK;
                    }
                }
                else
                {
                    /*nothing to do,just keep the format consistent*/
                }
            }
        }
        /*DTC + (not 0xFF nor 0xFE)*/
        else
        {
            /*calculate the remained size of Tx buffer,keep one byte to store record number*/
            CurChannelSize = (uint8)(ChannelSize - MsgLen - 1u);
            ReturnGetExtendedDataRecord = Dem_DcmGetExtendedDataRecordByDTC(
                                        Dtc,
                                        DEM_DTC_ORIGIN_PRIMARY_MEMORY,
                                        DtcExtendedDataRecordNumber,
                                        &Dcm_Channel[Offset + MsgLen + 1u],
                                        &CurChannelSize);
            if ((DEM_RECORD_OK == ReturnGetExtendedDataRecord)&&(CurChannelSize != 0u))
            {
                /*store extended data record number*/
                Dcm_Channel[Offset + MsgLen] = DtcExtendedDataRecordNumber;
                MsgLen = MsgLen + 1u;
                /*successfully store extended data,increase MsgLen*/
                MsgLen = MsgLen + CurChannelSize;
            }
            else if (DEM_RECORD_PENDING == ReturnGetExtendedDataRecord)
            {
                PendingFlag = TRUE;
            }
            else if ((DEM_RECORD_WRONG_DTC == ReturnGetExtendedDataRecord)||
            (DEM_RECORD_WRONG_DTCORIGIN == ReturnGetExtendedDataRecord)||
            (DEM_RECORD_WRONG_NUMBER == ReturnGetExtendedDataRecord))
            {
                /*if fail to get any request information,send NRC 0x31*/
                (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
                DsdInternal_ProcessingDone(ProtocolCtrlId);
                (void)Dem_DcmEnableDTCRecordUpdate();
                return E_NOT_OK;
            }
            else
            {
                /*nothing to do,just keep the format consistent*/
            }
        }
        /*enable DTC record update*/
        if (E_NOT_OK == Dem_DcmEnableDTCRecordUpdate())
        {
            NotAllowedFlag = TRUE;
        }

    }
    else if (DEM_DISABLE_DTCRECUP_WRONG_DTC == ReturnDisableDTCRecordUpdate)
    {
        NotAllowedFlag = TRUE;
    }
    else
    {}

	if(TRUE == NotAllowedFlag)
	{
		/*if fail to get any request information,send NRC 0x31*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	else if (TRUE == PendingFlag)
	{
		/*if some request info is not available yet,enter pending and wait for the next cycle*/
		Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
		return DCM_E_PENDING;
	}
	else
	{
        /* check tx data length */
        if((MsgLen) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
        {
            /*Pdu length is bigger than buffer size,ignore the request message */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
		/*assemble positive response*/
		Dcm_Channel[Offset] = 0x59;
		Dcm_Channel[Offset + 1u] = 0x06;
		SchM_Enter_Dcm(Dcm_MsgCtrl);
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = MsgLen;
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = MsgLen;
		Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
		SchM_Exit_Dcm(Dcm_MsgCtrl);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_OK;
	}
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/*******************************************/
#if(STD_ON == DCM_UDS_SERVICE0X19_0A_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19_0A(uint8 ProtocolCtrlId)
{
	uint8     TxChannelCtrlIndex;
	uint8     TxChannelCfgIndex;
	uint8     DtcStatus;
	uint8     MsgCtrlId;
	uint16    Offset;
	uint16    DtcCount = 0;
    uint16    Index;
	uint32    Dtc;
	boolean   NotAllowedFlag = FALSE;
	boolean   PendingFlag    = FALSE;
	boolean   Flag;
	Std_ReturnType  ret;
	Dcm_MsgLenType  MsgLen   = 2u;/*store response SID and echo of sub-function*/
	Dem_ReturnSetFilterType    ReturnSetDTCFilter;
	Dem_ReturnGetNextFilteredElementType      ReturnGetNextFilteredDTC;
	Dem_ReturnGetNumberOfFilteredDTCType  ReturnGetNumberOfFilteredDTC;

	MsgCtrlId = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
	/*check the massage length*/
	if (DCM_UDS0X19_SUBFUNC0X0A_REQ_DATA_LENGTH != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
	{
		/*the length of massage is not correct,send NRC 0x13*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

	/*find Tx buffer and offset*/
	TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
	TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
	Offset      = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;


#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
    if (0u == Dcm_PageBufferData.PageIndex)
    {
        Dcm_PageBufferData.PageTxOK = FALSE;
#endif
        Dcm_Channel[Offset] = 0x59u;
        Dcm_Channel[Offset + 1u] = 0x0Au;
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
        Dcm_PageBufferData.LastFilled = TRUE;
    }
    else
    {
        if (Dcm_PageBufferData.PageTxOK != TRUE)
        {
            Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
            return DCM_E_PENDING;
        }
        MsgLen = 0;
        Index = Dcm_PageBufferData.IloopOne;
        Dcm_PageBufferData.PageTxOK = FALSE;
        Dcm_PageBufferData.LastFilled = TRUE;
    }
#endif


	/*get DTCStatusAvailabilityMask*/
	ret = Dem_DcmGetDTCStatusAvailabilityMask(&Dcm_Channel[Offset + MsgLen]);
	if (E_OK == ret)
	{
        if(0u == Dcm_Channel[Offset + MsgLen])
        {
        	MsgLen = MsgLen + 1u;
        }
        else
        {
    		/*one byte for the storage of DTC status availability mask*/
    		MsgLen = MsgLen + 1u;
    		/*set DTC filter*/
    		ReturnSetDTCFilter = Dem_DcmSetDTCFilter(	0x00,
														DEM_DTC_KIND_ALL_DTCS,
														DEM_DTC_FORMAT_UDS,
														DEM_DTC_ORIGIN_PRIMARY_MEMORY,
														FALSE,
														DEM_SEVERITY_NO_SEVERITY,
														FALSE);
			if (DEM_FILTER_ACCEPTED == ReturnSetDTCFilter)
			{
				ReturnGetNumberOfFilteredDTC = Dem_DcmGetNumberOfFilteredDTC(&DtcCount);
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                if (Dcm_PageBufferData.TotalSize != 0UL)
                {
                    DtcCount = Dcm_PageBufferData.TotalDtcCount;
                }
#endif
				switch(ReturnGetNumberOfFilteredDTC)
				{
					case DEM_NUMBER_OK:
						 Flag = FALSE;
						 for(Index=0; (Index<DtcCount)&&(FALSE==Flag)
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                         && ((Dcm_PageBufferData.LastFilled == TRUE)
                                 || (Dcm_PageBufferData.TotalSize == 0UL))
#endif
						 ; Index++)
						 {
							ReturnGetNextFilteredDTC = Dem_DcmGetNextFilteredDTC(&Dtc,&DtcStatus);
							switch(ReturnGetNextFilteredDTC)
							{
								case  DEM_FILTERED_OK:
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                                      if (((Dcm_PageBufferData.TotalSize == 0UL)
                                              || (Index > Dcm_PageBufferData.IloopOne)
                                              || (Index == 0u))
                                              && (((Dcm_PageBufferData.TotalSize != 0UL)
                                                      && (Dcm_PageBufferData.TotalDtcCount > Index))
                                                      || (Dcm_PageBufferData.TotalSize == 0UL)))
#endif
                                      {
                                          Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc >> 16u);
                                          MsgLen  = MsgLen + 1u;
                                          Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc >> 8u);
                                          MsgLen  = MsgLen + 1u;
                                          Dcm_Channel[Offset + MsgLen] = (uint8)(Dtc);
                                          MsgLen  = MsgLen + 1u;
                                          Dcm_Channel[Offset + MsgLen] = DtcStatus;
                                          MsgLen  = MsgLen + 1u;
                                      }
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                                      if ((MsgLen)
                                          > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].
                                                  Dcm_DslBufferSize))
                                      {
                                          Dcm_PageBufferData.LastFilled = FALSE;
                                      }
#endif
									  break;
								case  DEM_FILTERED_NO_MATCHING_ELEMENT:
#if (TRUE == DCM_PAGEDBUFFER_ENABLED)
                                      if ((Dcm_PageBufferData.TotalSize != 0UL)
                                         && (Dcm_PageBufferData.TotalDtcCount > Index))
                                      {
                                          Dcm_Channel[Offset + MsgLen] = 0u;
                                          MsgLen  = MsgLen + 1u;
                                          Dcm_Channel[Offset + MsgLen] = 0u;
                                          MsgLen  = MsgLen + 1u;
                                          Dcm_Channel[Offset + MsgLen] = 0u;
                                          MsgLen  = MsgLen + 1u;
                                          Dcm_Channel[Offset + MsgLen] = 0u;
                                          MsgLen  = MsgLen + 1u;
                                          if ((MsgLen)
                                             > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].
                                                     Dcm_DslBufferSize))
                                          {
                                              Dcm_PageBufferData.LastFilled = FALSE;
                                          }
                                      }
                                      else
#endif
                                      {
                                          NotAllowedFlag = TRUE;
                                          Flag = TRUE;
                                      }
									  break;
								case  DEM_FILTERED_PENDING:
									  PendingFlag = TRUE;
									  Flag = TRUE;
									  break;
								case  DEM_FILTERED_BUFFER_TOO_SMALL:
									  NotAllowedFlag = TRUE;
									  Flag = TRUE;
									  break;
								default:
									  NotAllowedFlag = TRUE;
									  Flag = TRUE;
									  break;
							}
						}
						break;
					case DEM_NUMBER_FAILED:
						NotAllowedFlag = TRUE;
						break;
					case DEM_NUMBER_PENDING:
						PendingFlag = TRUE;
						break;
					default:
						NotAllowedFlag = TRUE;
						break;
				}
			}
        }
	}
	/************************************************/
    if (TRUE == NotAllowedFlag)
    {
    	/*if fail to get any request information,send NRC 0x22*/
    	(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_CONDITIONSNOTCORRECT);
    	DsdInternal_ProcessingDone(ProtocolCtrlId);
    	return E_NOT_OK;
    }
    if (TRUE == PendingFlag)
    {
    	/*if some request info is not available yet,enter pending and wait for the next cycle*/
    	Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
    	return DCM_E_PENDING;
    }

    /* check tx data length */
    if
#if(STD_ON == DCM_PAGEDBUFFER_ENABLED)
      (
#endif
       ((MsgLen) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
#if(STD_ON == DCM_PAGEDBUFFER_ENABLED)
        || (0u != Dcm_PageBufferData.TotalSize))
    {
        if(0u == Dcm_PageBufferData.TotalSize)
        {
            Dcm_PageBufferData.TotalSize = MsgLen;
            Dcm_PageBufferData.TotalDtcCount = DtcCount;
            DsdInternal_StartPagedProcessing(ProtocolCtrlId);
        }
        else
        {
            if (Dcm_PageBufferData.LastFilled == TRUE)
            {
                Dcm_PageBufferData.IloopOne = Index;
                Dcm_PageBufferData.ThisPageSize = (uint16)MsgLen;
            }
            else
            {
                Dcm_PageBufferData.IloopOne = Index - 1u;
                Dcm_PageBufferData.ThisPageSize = (uint16)(MsgLen - 4u);
            }
            Dcm_PageBufferData.PageIndex += 1u;
            Dcm_PageBufferData.Filled = TRUE;

            DsdInternal_ProcessPage(ProtocolCtrlId);
            if (Dcm_PageBufferData.TimeOut == TRUE)
            {
                return E_NOT_OK;
            }
            Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
            return DCM_E_PENDING;
        }
        if (Dcm_PageBufferData.TotalSize > Dcm_DslCfg.pDcmDslProtocol->
                pDcmDslProtocolRow[ProtocolCtrlId].DcmDslProtocolMaximumResponseSize)
        {
            /*Pdu length is bigger than Page buffer max size */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            DslInternal_InitPageBuffer();
            return E_NOT_OK;
        }
        Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
        return DCM_E_PENDING;
    }
#else
    {
        /*Pdu length is bigger than buffer size,ignore the request message */
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif

	/*assemble positive response*/
	SchM_Enter_Dcm(Dcm_MsgCtrl);
	Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = MsgLen;
	Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = MsgLen;
	Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
	SchM_Exit_Dcm(Dcm_MsgCtrl);
	DsdInternal_ProcessingDone(ProtocolCtrlId);
	return  E_OK;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/************************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x19SubfunctionAnalyse(
        uint8 ProtocolCtrlId,
        uint8 Subfunction)
{
	Std_ReturnType  ret;

	/*check sub-function entrance*/
	switch (Subfunction)
	{
	#if(STD_ON == DCM_UDS_SERVICE0X19_01_ENABLED)
		case DCM_REPORTNUMBEROFDTCBYSTATUSMASK:
			/*Sub-function:0x01*/
			ret = Dcm_UDS0x19_01(ProtocolCtrlId);
			break;
	#endif

	#if(STD_ON == DCM_UDS_SERVICE0X19_02_ENABLED)
		case DCM_REPORTDTCBYSTATUSMASK:
			/*Sub-function:0x02*/
			ret = Dcm_UDS0x19_02(ProtocolCtrlId);
			break;
	#endif

    #if(STD_ON == DCM_UDS_SERVICE0X19_03_ENABLED)
        case DCM_REPORTREPORTDTCSNAPSHOTIDENTIFICATION:
            /*Sub-function:0x03*/
            ret = Dcm_UDS0x19_03(ProtocolCtrlId);
                         break;
        #endif

	#if(STD_ON == DCM_UDS_SERVICE0X19_04_ENABLED)
		case DCM_REPORTDTCSNAPSHOTRECORDBYDTCNUMBER:
			/*Sub-function:0x04*/
			ret = Dcm_UDS0x19_04(ProtocolCtrlId);
			break;
	#endif

	#if(STD_ON == DCM_UDS_SERVICE0X19_06_ENABLED)
		case DCM_REPORTDTCEXTENDEDDATARECORDBYDTCNUMBER:
			/*Sub-function:0x06*/
			ret = Dcm_UDS0x19_06(ProtocolCtrlId);
			break;
	#endif

	#if(STD_ON == DCM_UDS_SERVICE0X19_0A_ENABLED)
		case DCM_REPORTSUPPORTEDDTC:
			/*Sub-function:0x0A*/
			ret = Dcm_UDS0x19_0A(ProtocolCtrlId);
			break;
	#endif

		default:
			/*if the sub-function is not supported,reset 'control resource' and send NRC 0x12*/
			(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SUBFUNCTIONNOTSUPPORTED);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			ret = E_NOT_OK;
			break;
	}

	return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

/*****************************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x19(
		Dcm_OpStatusType OpStatus,
		uint8 ProtocolCtrlId,
		P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_VAR) ErrorCode)
{
	uint8     MsgCtrlId;
	uint8     Subfunction;
	Std_ReturnType  ret;

    /*************************************************/
#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
    /*session check,check whether the current session supports the request service*/
    ret = DsdInternal_SesCheck(ProtocolCtrlId,SID_READ_DTC_INFORMATION);
    if (E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-073[DCM211]****/
        /*the current session does not support the request service,send NRC = 0x7F*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif

    /*************************************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
    /*security check,check whether the current security supports the request service*/
    ret = DsdInternal_SecurityCheck(ProtocolCtrlId,SID_READ_DTC_INFORMATION);
    if (E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-074[DCM217]****/
        /*the current security does not support the request service,send NRC = 0x33*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SECURITYACCESSDENIED);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif

	/*************************************************/
	/*if the required protocol is configuted,get the index of runtime datum*/
	MsgCtrlId = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
#if(STD_ON == DCM_MINIMUMLENGTH_CHECK_ENABLED)
	/*check the massage length*/
	if (Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen < DCM_UDS0X19_REQ_DATA_MINLENGTH)
	{
		/*the length of massage is not correct,send NRC 0x13*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
#endif

    /**************************************************/
	/*check whether the required sub-function is configured*/
	ret = Dcm_UdsSubServicesCheck(ProtocolCtrlId);
	if (E_NOT_OK == ret)
	{
		/*if the required reset type is not supported,send NRC 0x12*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SUBFUNCTIONNOTSUPPORTED);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
    ret = DsdInternal_SubSesCheck(ProtocolCtrlId,SID_READ_DTC_INFORMATION);
    if(E_NOT_OK == ret)
    {
        /****SWS_Dcm_00616****/
        /*the current session does not support the request sub service,send NRC = 0x7E*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SUBFUNCTIONNOTSUPPORTEDINACTIVESESSION);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

#endif

    /*************************************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
    /*security check,check whether the current security supports the request service*/
    ret = DsdInternal_SubSecurityCheck(ProtocolCtrlId,SID_READ_DTC_INFORMATION);
    if (E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-074[DCM217]****/
        /*the current security does not support the request service,send NRC = 0x33*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SECURITYACCESSDENIED);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif
    /**************************************************/

	Subfunction = Dcm_MsgCtrl[MsgCtrlId].Subfunction;
	/*check sub-function entrance*/
	ret = Dcm_Uds0x19SubfunctionAnalyse(ProtocolCtrlId, Subfunction);

	return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif
